package com.study.util.mail;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import javax.mail.Address;
import javax.mail.MessagingException;
import javax.mail.SendFailedException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.FileSystemResource;
import org.springframework.mail.MailSendException;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

@Component
public class MailUtils {

	private final Logger logger = LoggerFactory.getLogger(this.getClass());

	/**
	 * Spring官方提供的集成邮件服务的实现类，目前是Java后端发送邮件和集成邮件服务的主流工具。
	 */
	@Autowired
	private JavaMailSender mailSender;

	@Value("${spring.mail.username}")
	private String fromEmail;

	/**
	 * 发送文本邮件
	 * 
	 * @param to      收件人
	 * @param subject 标题
	 * @param content 正文
	 */
	public void sendSimpleMail(String to, String subject, String content) {
		// 创建SimpleMailMessage对象
		SimpleMailMessage message = new SimpleMailMessage();
		// 邮件发送人
		message.setFrom(fromEmail);
		// 邮件接收人
		message.setTo(to);
		// 邮件主题
		message.setSubject(subject);
		// 邮件内容
		message.setText(content);
		// 发送邮件
		mailSender.send(message);
	}

	/**
	 * 发送html邮件
	 * 
	 * @param to      收件人
	 * @param subject 标题
	 * @param content 正文
	 */
	public void sendHtmlMail(String to, String subject, String content) {
		try {
			// 注意这里使用的是MimeMessage
			MimeMessage message = mailSender.createMimeMessage();
			MimeMessageHelper helper = new MimeMessageHelper(message, true);
			// 邮件发送人
			helper.setFrom(fromEmail);
			// 邮件接收人，设置多个收件人地址
			InternetAddress[] internetAddresses = InternetAddress.parse(to);
			helper.setTo(internetAddresses);
			// 邮件主题
			helper.setSubject(subject);
			// 第二个参数：格式是否为html
			helper.setText(content, true);
			// 发送
			mailSender.send(message);
			// 日志信息
			logger.info("邮件已发送。");
		} catch (MessagingException e) {
			logger.error("发送邮件时发生异常！", e);
		}
	}

	/**
	 * 发送带附件的邮件
	 * 
	 * @param to       收件人
	 * @param subject  主题
	 * @param content  内容
	 * @param filePath 附件
	 */
	public void sendAttachmentsMail(String to, String subject, String content, String filePath) {
		MimeMessage message = mailSender.createMimeMessage();
		// 要带附件第二个参数设为true
		MimeMessageHelper helper;
		try {
			helper = new MimeMessageHelper(message, true);
			helper.setFrom(fromEmail);
			helper.setTo(to);
			helper.setSubject(subject);
			helper.setText(content, true);

			FileSystemResource file = new FileSystemResource(new File(filePath));

			String fileName = filePath.substring(filePath.lastIndexOf(File.separator));
			helper.addAttachment(fileName, file);
			mailSender.send(message);

			// 日志信息
			logger.info("邮件已发送。");
		} catch (MessagingException e) {
			logger.error("发送邮件时发生异常！", e);
		}
	}

	public void sendHtmlMail(String[] to, String[] cc, String subject, String content) {
		MimeMessage message = mailSender.createMimeMessage();
		MimeMessageHelper helper = null;
		try {
			// true表示需要创建一个multipart message
			helper = new MimeMessageHelper(message, true);
			helper.setFrom(fromEmail);
			helper.setTo(to);
			helper.setCc(cc);
			helper.setSubject(subject);
			helper.setText(content, true);

			mailSender.send(message);
			logger.info("sendHtmlMail success.from：" + fromEmail);
		} catch (Throwable e) {
			logger.error("sendHtmlMail fail.", e);
			String[] invalid = getInvalidAddress(e);
			if (invalid != null) {
				sendHtmlMail(filterByArray(to, invalid), filterByArray(cc, invalid), subject, content);
			}
		}
	}

	/**
	 * 从异常获取无效地址
	 * 
	 * @param e
	 * @return
	 */
	private String[] getInvalidAddress(Throwable e) {
		if (e == null) {
			return null;
		}
		if (e instanceof MailSendException) {
			Exception[] exceptions = ((MailSendException) e).getMessageExceptions();
			for (Exception exception : exceptions) {
				if (exception instanceof SendFailedException) {
					return getStringAddress(((SendFailedException) exception).getInvalidAddresses());
				}
			}
		}

		if (e instanceof SendFailedException) {
			return getStringAddress(((SendFailedException) e).getInvalidAddresses());
		}

		return null;
	}

	/**
	 * 将Address[]转成String[]
	 * 
	 * @param addresses
	 * 
	 * @return
	 */
	private String[] getStringAddress(Address[] addresses) {
		List<String> invalid = new ArrayList<>();
		for (Address address : addresses) {
			String aa = ((InternetAddress) address).getAddress();
			if (StringUtils.hasLength(aa)) {
				invalid.add(aa);
			}
		}
		return invalid.stream().distinct().toArray(String[]::new);
	}

	/**
	 * 过滤数组source，规则为数组元素包含了数组filter中的元素则去除
	 * 
	 * @param source
	 * @param filter
	 * @return
	 */
	private String[] filterByArray(String[] source, String[] filter) {
		List<String> result = new ArrayList<>();
		for (String s : source) {
			boolean contains = false;
			for (String f : filter) {
				if (s.contains(f)) {
					contains = true;
					break;
				}
			}
			if (!contains) {
				result.add(s);
			}
		}
		return result.stream().toArray(String[]::new);
	}

}
